﻿#ifndef _OI_PLSCANNER_CALIB_HPP_
#define _OI_PLSCANNER_CALIB_HPP_

#include "Core/OiCore.hpp"
#include "Core/OiCalib.hpp"

namespace Oi
{
    namespace PLScannerCore
    {
        class OI_PLSCANNER_CORE_API Calib : public QObject
        {
            Q_OBJECT
        public:

            struct Data
            {
                int _model = -1;
                float _Sx = 0.0;
                float _Sy = 0.0;
                float _Cx = 0.0;
                float _Cy = 0.0;
                float _F = 0.0;
                float _K = 0.0;
                float _K1 = 0.0;
                float _K2 = 0.0;
                float _K3 = 0.0;
                float _K4 = 0.0;
                float _P1 = 0.0;
                float _P2 = 0.0;
                float _posX = 0.0;
                float _posY = 0.0;
                float _posZ = 0.0;
                float _posRx = 0.0;
                float _posRy = 0.0;
                float _posRz = 0.0;
            }_data;

        public:
            Math::Pose3d _pos;
            Math::Point4d _plane;
            Math::Matrix44d _matrix;
            Math::Matrix44d _invert;

        public:
            const float NaN = std::numeric_limits<float>::quiet_NaN();

        public:
            Calib();

            Calib(int mode, float Sx, float Sy, float Cx, float Cy, float F, float K, float K1, float K2, float K3, float K4, float P1, float P2,
                float posX, float posY, float posZ, float posRx, float posRy, float posRz);

            Calib(int mode, float Sx, float Sy, float Cx, float Cy, float F, float K, float K1, float K2, float K3, float K4, float P1, float P2,
                Math::Pose3d pos);

            Calib(const Core::Calib& cc);

            Calib(const QString& file);

            bool isValid();

            void load(Data& d);

            void load(int mode, float Sx, float Sy, float Cx, float Cy, float F, float K, float K1, float K2, float K3, float K4, float P1, float P2,
                float posX, float posY, float posZ, float posRx, float posRy, float posRz);

            void load(int mode, float Sx, float Sy, float Cx, float Cy, float F, float K, float K1, float K2, float K3, float K4, float P1, float P2,
                Math::Pose3d pos);

            void load(const Core::Calib& cc);

            void load(const QString& file);

            inline Math::Point2d toWorldHelper(const Math::Point2d& point) const;

            inline Math::Point2d toImageHelper(const Math::Point2d& point) const;

        public:
            Math::Point3d toWorld(const Math::Point2d& point) const;

            Core::PointMapPtr toWorld(const Core::RangeMapPtr& rangeMap, int offsetX = 0, int offsetY = 0) const;

            Math::Point2d toImage(const Math::Point2d& world) const;

        public:
            bool saveDataToHasp();
            bool readDataFromHasp();

            bool saveSeriesToHasp(const std::string s);
            bool readSeriesFromHasp(std::string& s);

        public:
            static const int seriesSize = 12;

        public:
            static Calib* OiCalib();
        };

        class OI_PLSCANNER_CORE_API PosCalib
        {
        public:
            struct Data
            {
                float _K1 = 0.0;
                float _K2 = 1.0;
                float _K3 = 0.0;

            }_data;

        public:
            PosCalib();
            PosCalib(const PosCalib& p);

        public:
            double toPos(QPointF camCoord);
            double toCam(double pos, double camX = 0.0);

        public:
            bool calib(QList<double> xPos, QList<double> yPos, QList<double> actPos);

        public:
            PosCalib& operator=(const PosCalib& p);

        public:
            static PosCalib* OiPosCalib();
        };
    }
}


#endif
